﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;

namespace Microsoft.Extensions.Caching.Memory
{
    public static class MemoryCacheExtension
    {
        const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
        public static IEnumerable GetKeys(this IMemoryCache memoryCache)
        {
            FieldInfo fieldInfo = memoryCache.GetType().GetField("_entries", flags);
            if (fieldInfo != null)
            {
                var entries = fieldInfo.GetValue(memoryCache) as IDictionary;
                if (entries != null)
                {

                    foreach (var item in entries.Keys)
                    {
                        yield return item;
                    }
                }
            }
            yield break;
        }

        public static T GetOrCreate<T>(this IMemoryCache memoryCache, object key, Func<T> createFactory, int minutes)
        {
            return memoryCache.GetOrCreate(key, ent =>
             {
                 ent.SetSlidingExpiration(TimeSpan.FromMinutes(minutes));
                 return createFactory();
             });
        }

        public static Task<T> GetOrCreateAsync<T>(this IMemoryCache memoryCache, object key, Func<Task<T>> createFactory, int minutes)
        {
            return memoryCache.GetOrCreateAsync(key, ent =>
            {
                ent.SetSlidingExpiration(TimeSpan.FromMinutes(minutes));
                return createFactory();
            });
        }
        
        public static void RemoveStartsWith(this IMemoryCache memoryCache, string keyStarts)
        {
            foreach (var item in memoryCache.GetKeys())
            {
                if (item is string str && str.StartsWith(keyStarts))
                {
                    memoryCache.Remove(item);
                }
            }
        }
    }
}
